<template>
  <div class="inline-edit" @click.stop="handleClick" ref="wrapper">
    <input
      v-model="innerValue"
      v-if="isEditing"
      placeholder="文本不能为空"
      ref="inputRef"
      :class="{ 'input-error': !validateCheck }"
      class="ant-input"
    />
    <slot v-else :text="innerValue"
      ><span>{{ innerValue }}</span></slot
    >
  </div>
</template>
<script lang="ts">
import { defineComponent, ref, watch, computed, nextTick } from "vue";
import useKeyPress from "@/hooks/useKeyPress";
import useClickOutside from "@/hooks/useClickOutside";
export default defineComponent({
  name: "inline-edit",
  props: {
    value: {
      type: String,
      required: true,
    },
  },
  emits: ["change"],
  setup(props, { emit }) {
    const innerValue = ref(props.value);
    const isEditing = ref(false);
    let cachedOldValue = "";
    const wrapper = ref<null | HTMLElement>(null);
    const inputRef = ref<null | HTMLInputElement>(null);
    const validateCheck = computed(() => innerValue.value.trim() !== "");
    const isOutside = useClickOutside(wrapper);
    const handleClick = () => {
      isEditing.value = true;
    };

    watch(isOutside, (newValue) => {
      if (!validateCheck.value) {
        return;
      }
      if (newValue && isEditing.value) {
        isEditing.value = false;
        emit("change", innerValue.value);
      }
      isOutside.value = false;
    });
    useKeyPress("Enter", () => {
      if (!validateCheck.value) {
        return;
      }
      if (isEditing.value) {
        isEditing.value = false;
        emit("change", innerValue.value);
      }
    });
    useKeyPress("Escape", () => {
      if (isEditing.value) {
        isEditing.value = false;
        innerValue.value = cachedOldValue;
      }
    });
    watch(
      () => props.value,
      (newValue) => {
        innerValue.value = newValue;
      }
    );
    watch(isEditing, async (isEditing) => {
      if (isEditing) {
        cachedOldValue = innerValue.value;
        await nextTick();
        if (inputRef.value) {
          inputRef.value.focus();
        }
      }
    });
    return {
      innerValue,
      isEditing,
      handleClick,
      validateCheck,
      wrapper,
      inputRef,
    };
  },
});
</script>
